package com.zzq.controller;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sun.jersey.api.client.Client;
import com.zzq.Model.User;
import com.zzq.mapper.ArticleMapper;
import com.zzq.mapper.UserMapper;
import com.zzq.utils.*;

import io.jsonwebtoken.Claims;
import io.swagger.annotations.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

@Api("用户接口")
@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    UserMapper userMapper;
    @Autowired
    ArticleMapper articleMapper;

    private String imgPath = "upload/user/";    //后台图片保存地址

    private String uploadHost = "http://120.76.157.21:20041/";    //项目host路径

    @ApiOperation(value = "注册用户", response = User.class)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType="query", name = "username", value = "用户名", required = true, dataType = "String"),
            @ApiImplicitParam(paramType="query", name = "password", value = "密码(1.密码必须由字母、数字组成，区分大小写 2.密码长度为8-18位)", required = true, dataType = "String"),
            @ApiImplicitParam(paramType="query", name = "passwordConfirm", value = "确认密码", required = true, dataType = "String")
    })
    @PostMapping("register.do")
    @ResponseBody
    public IResult registerUser(HttpServletRequest request) {
        try {
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            String passwordConfirm = request.getParameter("passwordConfirm");
            if(username == null || password == null || passwordConfirm == null || "".equals(username) || "".equals(password) || "".equals(passwordConfirm)) {
                return IResult.error("用户名和密码不能为空");
            }
            if(!password.equals(passwordConfirm)) {
                return IResult.error("两个密码不一致");
            }
            if(!PasswordPowerTest.testPassword(password) && !"admin".equals(username)) {
                return IResult.error("密码强度不合格");
            }
            User user = userMapper.getByUsername(username);
            if(user != null) {
                return IResult.error("用户名已存在");
            }
            String md5Password = MD5.md5(password);
            User user1 = new User();
            user1.setUsername(username).setPassword(md5Password).setNickName(username);
            userMapper.add(user1);
            return IResult.success("注册成功", user1);
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("删除选定用户")
    @ApiImplicitParam(paramType="body", name = "userIds", value = "用户编号列表(格式如: [12,13])", required = true, dataType = "Integer")
    @DeleteMapping("admin/deleteByIds.do")
    @ResponseBody
    public IResult deleteByIds(@RequestBody List<Integer> userIds) {
        try {
            for(int id : userIds) {
                User user = userMapper.getById(id);
                if(user.getAvatar() != null && !"".equals(user.getAvatar())) {
                    Upload.delete(user.getAvatar());
                }
            }

            userMapper.deleteByIds(userIds);
            return IResult.success("删除成功");
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("删除指定id用户")
    @ApiImplicitParam(paramType="path", name = "userId", value = "用户编号", required = true, dataType = "Integer")
    @DeleteMapping("admin/{userId}")
    @ResponseBody
    public IResult deleteById(@PathVariable("userId") int userId) {
        try {
            User user = userMapper.getById(userId);

            if(user == null) {
                return IResult.error("用户不存在");
            }

            if(user.getAvatar() != null && !"".equals(user.getAvatar())) {
                Upload.delete(user.getAvatar());
            }

            userMapper.deleteById(userId);
            return IResult.success("删除成功");
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("更新用户权限, isSuperUser：0:普通用户，1:管理员")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType="query", name = "id", value = "用户编号", dataType = "Integer"),
            @ApiImplicitParam(paramType="query", name = "isSuperUser", value = "是否是管理员", dataType = "Integer")
    })
    @PostMapping("admin/updatePermission.do")
    @ResponseBody
    public IResult updatePermission(HttpServletRequest request) {
        try {
            int id = Integer.parseInt(request.getParameter("id"));
            int isSuperUser = Integer.parseInt(request.getParameter("isSuperUser"));
            User user = null;
            user = userMapper.getById(id);
            if(user == null) {
                return IResult.error("用户不存在");
            }
            userMapper.editPermission(id, isSuperUser);
            return IResult.success("修改成功");
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("更新用户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType="query", name = "nickName", value = "昵称", dataType = "String"),
            @ApiImplicitParam(paramType="query", name = "email", value = "邮箱", dataType = "String"),
            @ApiImplicitParam(paramType="query", name = "phone", value = "电话", dataType = "String"),
            @ApiImplicitParam(paramType="query", name = "intro", value = "介绍", dataType = "String")
    })
    @PostMapping("updateInfo.do/{id}")
    @ResponseBody
    public IResult updateInfo(@RequestHeader("token") String token, HttpServletRequest request) {
        try {
            String nickName = request.getParameter("nickName");
            String email = request.getParameter("email");
            String phone = request.getParameter("phone");
            String intro = request.getParameter("intro");

            Claims claims = JWTUtil.verifyToken(token);
            int userId = Integer.parseInt((String) claims.get("jti"));

            User user = null;
            user = userMapper.getById(userId);
            if(user == null) {
                return IResult.error("用户不存在");
            }
            userMapper.editInfo(userId, nickName, email, phone, intro);
            return IResult.success("修改成功");
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("修改密码")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType="path", name = "id", value = "用户编号", dataType = "Integer"),
            @ApiImplicitParam(paramType="query", name = "password", value = "密码", dataType = "String"),
            @ApiImplicitParam(paramType="query", name = "passwordConfirm", value = "确认密码", dataType = "String"),
    })
    @PostMapping("updatePassword.do/{id}")
    @ResponseBody
    public IResult updatePassword(@PathVariable("id") int id, @RequestHeader("token") String token, HttpServletRequest request) {
        try {
            String password = request.getParameter("password");
            String passwordConfirm = request.getParameter("passwordConfirm");

            User user = null;
            user = userMapper.getById(id);
            if(user == null) {
                return IResult.error("用户不存在");
            }

            Claims claims = JWTUtil.verifyToken(token);
            int userId = Integer.parseInt((String) claims.get("jti"));
            if(id == userId || userMapper.getById(userId).getIsSuperuser() == 1) {
                if(password == null || passwordConfirm == null || "".equals(password) || "".equals(passwordConfirm)) {
                    return IResult.error("密码不能为空");
                }
                if(!password.equals(passwordConfirm)) {
                    return IResult.error("两个密码不一致");
                }
                if(!PasswordPowerTest.testPassword(password)) {
                    return IResult.error("密码强度不合格");
                }
                String md5Password = MD5.md5(password);
                userMapper.editPassword(id, md5Password);
                return IResult.success("修改成功");
            }
            return IResult.error("只有自己和管理员可以修改密码");
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("通过用户名修改密码")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType="query", name = "username", value = "用户名", dataType = "String"),
            @ApiImplicitParam(paramType="query", name = "password", value = "密码", dataType = "String"),
            @ApiImplicitParam(paramType="query", name = "passwordConfirm", value = "确认密码", dataType = "String"),
    })
    @PostMapping("updatePassword.do")
    @ResponseBody
    public IResult updatePasswordForUsername(@RequestParam("username") String username, @RequestHeader("token") String token, HttpServletRequest request) {
        try {
            String password = request.getParameter("password");
            String passwordConfirm = request.getParameter("passwordConfirm");

            User user = userMapper.getByUsername(username);
            if(user == null) {
                return IResult.error("用户不存在");
            }
            int id = user.getId();

            Claims claims = JWTUtil.verifyToken(token);
            int userId = Integer.parseInt((String) claims.get("jti"));
            if(id == userId || userMapper.getById(userId).getIsSuperuser() == 1) {
                if(password == null || passwordConfirm == null || "".equals(password) || "".equals(passwordConfirm)) {
                    return IResult.error("密码不能为空");
                }
                if(!password.equals(passwordConfirm)) {
                    return IResult.error("两个密码不一致");
                }
                if(!PasswordPowerTest.testPassword(password)) {
                    return IResult.error("密码强度不合格");
                }
                String md5Password = MD5.md5(password);
                userMapper.editPassword(id, md5Password);
                return IResult.success("修改成功");
            }
            return IResult.error("只有自己和管理员可以修改密码");
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    /**
     * 上传用户头像
     * @param request
     * @param response
     */
    @ApiOperation("修改当前用户头像, 头像传过来的名字是img")
    @ApiImplicitParam(paramType="body", name = "img", value = "图片", dataType = "Picture")
    @PutMapping("updateHeadImg.do")
    @ResponseBody
    public IResult uploadSysHeadImg(HttpServletRequest request, HttpServletResponse response, @RequestHeader("token") String token){
        try {
            Claims claims = JWTUtil.verifyToken(token);
            int userId = Integer.parseInt((String) claims.get("jti"));


            User user = userMapper.getById(userId);
            if(user.getAvatar() != null && !"".equals(user.getAvatar())) {
                Upload.delete(user.getAvatar());
            }

            IResult iResult = new IResult();

            MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
            MultipartHttpServletRequest Murequest = resolver.resolveMultipart(request);
            MultipartFile file = Murequest.getFile("img");

            // 实例化一个jersey
            Client client = new Client();

            String fileName = new String();
            String realPath = new String();
            String uploadInfo = Upload.upload(client, file, request, response, uploadHost, imgPath);
            if(!"".equals(uploadInfo)) {    //上传成功
                String[] infoList = uploadInfo.split(";");
                fileName = infoList[0];    //文件名
                // 1为相对路径
                realPath = infoList[2];    //真实完整路径
            } else {    //上传失败
                fileName = "";
                realPath = "";
            }

            iResult.setCode(100);
            userMapper.editAvatar(userId, realPath);
            iResult.setMsg("上传成功");
            iResult.getMap().put("fileName", fileName);
            iResult.getMap().put("realPath", realPath);
            return iResult;
        } catch (Exception e) {
            return IResult.error("上传失败");
        }
    }

    @ApiOperation("根据id获取指定用户")
    @ApiImplicitParam(paramType="path", name = "userId", value = "用户编号", dataType = "Integer")
    @GetMapping("{userId}")
    @ResponseBody
    public IResult<User> getById(@PathVariable("userId") int userId) {
        try {
            User user = userMapper.getById(userId);
            if(user != null) {
                return IResult.success(user);
            } else {
                return IResult.error("查无此人");
            }
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("根据username获取指定用户")
    @ApiImplicitParam(paramType="query", name = "username", value = "用户名", dataType = "String")
    @GetMapping("getByUsername.do")
    @ResponseBody
    public IResult<User> getByUsername(String username) {
        try {
            User user = userMapper.getByUsername(username);
            if(user != null) {
                return IResult.success(user);
            } else {
                return IResult.error("查无此人");
            }
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("根据nickname获取指定用户")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType="query", name = "pageNo", value = "页码", dataType = "Integer"),
            @ApiImplicitParam(paramType="query", name = "pageNum", value = "一页显示的数量", dataType = "Integer"),
            @ApiImplicitParam(paramType="query", name = "nickName", value = "昵称", dataType = "String")
    })
    @GetMapping("getByNickName.do")
    @ResponseBody
    public IResult<User> getByNickName(@RequestParam(value = "pageNo", defaultValue = "1") int pageNo, @RequestParam(value = "pageNum", defaultValue = "5") int pageNum, String nickName) {
        try {
            Page<Object> objects = PageHelper.startPage(pageNo, pageNum);
            List<User> users = userMapper.getByNickName(nickName);
            PageInfo<User> pageInfo = new PageInfo<User>(users);
            return IResult.success(pageInfo);
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("获取所有用户")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType="query", name = "pageNo", value = "页码", dataType = "Integer"),
            @ApiImplicitParam(paramType="query", name = "pageNum", value = "一页显示的数量", dataType = "Integer")
    })
    @GetMapping("admin")
    @ResponseBody
    public IResult<User> getAll(@RequestParam(value = "pageNo", defaultValue = "1") int pageNo, @RequestParam(value = "pageNum", defaultValue = "5") int pageNum) {
        try {
            Page<Object> objects = PageHelper.startPage(pageNo, pageNum);
            List<User> users = userMapper.getAll();
            PageInfo<User> pageInfo = new PageInfo<User>(users);
            return IResult.success(pageInfo);
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("登录用户，采用JWT技术，会返回一个token，其他请求需要将token放进header中才能访问，token过期时间为一天，若带着token访问接口则会从当前时间续期一天")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType="query", name = "username", value = "用户名", dataType = "String"),
            @ApiImplicitParam(paramType="query", name = "password", value = "密码", dataType = "String")
    })
    @GetMapping("login.do")
    @ResponseBody
    public IResult<User> login(String username, String password) {
        try {
            User user = null;
            user = userMapper.getByUsername(username);
            if(user != null) {
                String md5Password = MD5.md5(password);
                user = userMapper.getByUserNameAndPassword(username, md5Password);
                if (user != null) {
                    // 生成token
                    String token = JWTUtil.generateToken(String.valueOf(user.getId()), "Kuroko-Security-Basic", user.getUsername());
                    // 向浏览器返回token，客户端收到此token后存入cookie中，或者h5的本地存储
                    return IResult.success(user, token);
                } else {
                    return IResult.error("登录失败，用户名或密码错误！");
                }
            } else {
                return IResult.error("请注册用户");
            }
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("登录管理员用户(管理员账户: admin, 密码: 123)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType="query", name = "username", value = "用户名", dataType = "String"),
            @ApiImplicitParam(paramType="query", name = "password", value = "密码", dataType = "String")
    })
    @GetMapping("loginAdmin.do")
    @ResponseBody
    public IResult<User> loginAdmin(String username, String password) {
        try {
            User user = null;
            user = userMapper.getByUsername(username);
            if(user != null) {
                if(user.getIsSuperuser() == 0) {
                    return IResult.error("您不是管理员");
                }
                String md5Password = MD5.md5(password);
                user = userMapper.getByUserNameAndPassword(username, md5Password);
                if (user != null) {
                    // 生成token
                    String token = JWTUtil.generateToken(String.valueOf(user.getId()), "Kuroko-Security-Basic", user.getUsername());
                    // 向浏览器返回token，客户端收到此token后存入cookie中，或者h5的本地存储
                    return IResult.success(user, token);
                } else {
                    return IResult.error("登录失败，用户名或密码错误！");
                }
            } else {
                return IResult.error("用户不存在");
            }
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }

    @ApiOperation("通过登录用户获取用户的文章总被访问量，文章数量，总浏览量，文章总点赞数")
    @GetMapping("getUserRelatedInfo.do")
    @ResponseBody
    public IResult getUserRelatedInfo(@RequestHeader("token") String token) {
        try {
            Claims claims = JWTUtil.verifyToken(token);
            int userId = Integer.parseInt((String) claims.get("jti"));

            int totalViewCount = articleMapper.getTotalViewByUserId(userId);
            int articleCount = articleMapper.getCountByUserId(userId);
            int readCount = userMapper.getById(userId).getReadCount();
            int likesCount = articleMapper.getLikesByUserId(userId);
            IResult iResult = new IResult();
            iResult.getMap().put("totalViewCount", totalViewCount);
            iResult.getMap().put("articleCount", articleCount);
            iResult.getMap().put("readCount", readCount);
            iResult.getMap().put("likesCount", likesCount);
            return iResult;
        } catch (Exception e) {
            Log.LogWarn(e.toString());
            return IResult.error(e.toString());
        }
    }
}
